package rpg.animation
{
	import flash.display.BlendMode;
	import flash.filters.BitmapFilter;
	import flash.geom.ColorTransform;
	import flash.utils.Dictionary;

	import rpg.Utils.Log;
	import rpg.Utils.Val;
	import rpg.data.ResData;
	import rpg.interfaces.IDestroy;
	import rpg.manager.AnimationManager;
	import rpg.manager.GameManager;
	import rpg.resource.PreLoad;
	import rpg.resource.Resource;
	import rpg.resource.Resources;
	import rpg.resource.SWFResource;

	/**
	 * 普通动画类，动画由一组帧图片构成
	 * @author hyy
	 *
	 */
	public class Animation implements IDestroy
	{
		/**
		 * 根据下载ID储存一组动画序列帧
		 */
		protected static var saveAnimationFrames : Dictionary = new Dictionary();
		/**
		 * 根据下载地址,是否需要下载动画
		 */
		protected static var loadAnimationFrames : Dictionary = new Dictionary();
		/**
		 * 当前动画帧
		 */
		public var curFrame : Frame;
		/**
		 * 总帧数
		 */
		public var frameCount : int;
		private var _frames : Array = [];
		/**
		 * 临时的动画时间
		 */
		protected var tmpElapsedTime : int;
		/**
		 * 当前动画已持续的时间
		 */
		public var curAnimationDurations : int;
		/**
		 * 当前的动画帧索引
		 */
		public var curFrameIndex : int;
		/**
		 * 该动画的id
		 */
		public var id : String;
		/**
		 * 下载地址
		 */
		public var resoureceId : String;
		/**
		 * 是否暂停播放
		 */
		public var isPaused : Boolean;
		/**
		 * 当前帧是否到最后一帧
		 */
		public var isEnd : Boolean;
		/**
		 *  是否播放次数结束
		 */
		public var isLoopEnd : Boolean;
		/**
		 * 动画总共需要循环的次数
		 */
		public var loops : int = 0;
		/**
		 * 当前已经循环的次数
		 */
		protected var curLoop : int;

		/**
		 * 是否已经销毁
		 */
		public var isDestroy : Boolean;
		/**
		 * 中心点
		 */
		public var centerX : int;
		public var centerY : int;
		/**
		 * 混合模式
		 */
		public var blendMode : String = BlendMode.NORMAL;

		public var filter : BitmapFilter;

		public var colorTransform : ColorTransform;

		/**
		 * 是否需要加载动画
		 */
		protected var isNeedDownLoadAnimation : Boolean = true;

		public function Animation(id : String)
		{
			this.id = id;
		}

		/**
		 * 跳到第几帧
		 */
		public function gotoFrame(index : int) : Frame
		{
			var frameCount : int = frameCount - 1;
			if(index < 0)
				index = 0;
			curFrameIndex = index;
			if(frameCount < 0 || index > frameCount)
				return null;
			if(isNeedDownLoadAnimation)
				loadAnimation();
			isEnd = index == frameCount;
			curFrame = _frames[index];
			return curFrame;
		}

		/**
		 * 添加帧
		 * @param frame
		 * @param index 在指定位置添加帧
		 *
		 */
		public function addFrame(frame : Frame , index : int = -1) : void
		{
			if(index == -1)
				index = frameCount;
			if(_frames)
			{
				_frames.splice(index , 0 , frame);
				frameCount = _frames.length;
			}
		}

		/**
		 * 获得帧
		 * @param index
		 * @return
		 *
		 */
		public function getFrame(index : int) : Frame
		{
			if(index < 0 || index >= frameCount)
				return null;
			if(isNeedDownLoadAnimation)
				loadAnimation();
			return _frames[index];
		}

		/**
		 * 动画帧序列
		 */
		public function get frames() : Array
		{
			return _frames;
		}

		/**
		 * @private
		 */
		public function set frames(value : Array) : void
		{
			_frames = value;
			if(_frames)
				frameCount = _frames.length;
		}

		/**
		 * 设置每个动作的持续时间
		 * @param duration
		 *
		 */
		public function setDration(duration : int) : void
		{
			if(duration <= 0)
				return;
			for each(var frame : Frame in _frames)
			{
				frame.duration = duration;
			}
		}

		/**
		 * 获取下一帧，如果动画暂停，返回当前帧
		 * @param elapsedTime 帧时间
		 * @param addFrameDuration 附加间隔
		 * @return 返回当前播放的帧
		 */
		public function tryNext(elapsedTime : int , addFrameDuration : int = 0) : Frame
		{
			if(!curFrame)
				return gotoFrame(0);
			if(isPaused)
				return curFrame;
			if(addFrameDuration == 0)
				addFrameDuration = curFrame.duration;

			tmpElapsedTime += elapsedTime;
			curAnimationDurations += elapsedTime;

			//如果该帧停留的次数超过了定义的次数，获取下一帧
			if(tmpElapsedTime < addFrameDuration)
				return curFrame;
			//要强制跳的帧数
			var skipFrames : int = tmpElapsedTime / addFrameDuration;
			if(skipFrames >= 2)
			{
				var tmpCurFrameIndex : int = curFrameIndex;
				//大于一帧的跳帧情况
				do
				{
					tmpElapsedTime -= addFrameDuration;
					tmpCurFrameIndex += 1;
					if(tmpCurFrameIndex >= frameCount)
					{
						tmpCurFrameIndex = 0;
					}
					addFrameDuration = getFrame(tmpCurFrameIndex).duration;
				} while(tmpElapsedTime >= addFrameDuration)
			}
			else
			{
				//求余值 
				tmpElapsedTime %= addFrameDuration;
			}
			curFrameIndex += skipFrames;

			//如果播放到动画尾，重新从第一帧开始播放
			if(curFrameIndex >= frameCount)
			{
				curLoop++;
				isEnd = true;
				//从0帧开始跳转 当前帧索引 相对于 总帧数 的余数
				curFrameIndex = curFrameIndex % frameCount;
				//如果需要记录结束 ，则不跳转
				if(loops != 0 && curLoop >= loops)
				{
					tmpElapsedTime += curFrameIndex * addFrameDuration;
					gotoFrame(frameCount - 1);
					isLoopEnd = true;
				}
				else
				{
					curAnimationDurations = 0;
				}
			}
			else
			{
				isEnd = false;
			}
			gotoFrame(curFrameIndex);
			return curFrame;
		}

		/**
		 * 加载动画
		 * @param resoureceId
		 *
		 */
		public function loadAnimation() : void
		{
			if(!isNeedDownLoadAnimation)
				return;
			isNeedDownLoadAnimation = false;
			if(loadAnimationFrames[resoureceId])
				return;
			loadAnimationFrames[resoureceId] = true;
			Log.print("正在加载:" , PreLoad.resUrl + resoureceId);
			Resources.getInstance().preload(PreLoad.resUrl + resoureceId , ResData.SWF , Val.LOAD_LVEVEL_ROLE , animationComplete);
		}

		/**
		 * 完成动画加载,把图片加载到frame里面
		 * @param res
		 *
		 */
		protected function animationComplete(res : Resource) : void
		{
			for each(var frame : Frame in _frames)
			{
				var resClass : Class = SWFResource(res).getAssetClass("Pic" + frame.name);
				frame.frameClass = resClass;
			}
		}

		/**
		 * 根据一组动画描述，创建出 一组动画序列帧
		 * @param animationDes
		 * @return
		 *
		 */
		public function createAnimationFrame(animationDes : AnimationDescription) : void
		{
			centerX = animationDes.centerX;
			centerY = animationDes.centerY;
			blendMode = animationDes.blendMode;
			filter = animationDes.filter;
			resoureceId = animationDes.resoureceId;
			isNeedDownLoadAnimation = loadAnimationFrames[resoureceId] == null;
			if(saveAnimationFrames[id])
			{
				frames = saveAnimationFrames[id];
				return;
			}
			var tmpFrames : Array = [];
			var frameCount : int = animationDes.frameNames.length;
			for(var i : int = 0 ; i < frameCount ; i++)
			{
				var frame : Frame = new Frame();
				frame.name = animationDes.frameNames[i];
				frame.duration = animationDes.durations[i];
				frame.offsetX = animationDes.offsetXs[i];
				frame.offsetY = animationDes.offsetYs[i];
				if(frame.duration == 0)
					frame.duration = 120;
				frame.frameClass = null;
				tmpFrames.push(frame);
			}
			this.frames = tmpFrames;
			saveAnimationFrames[id] = frames;
		}

		public function destroy() : void
		{
			for each(var frame : Frame in _frames)
			{
				frame.destory();
			}
			filter = null;
			curFrame = null;
			colorTransform = null;
		}
	}
}